# -*- coding: utf-8 -*-
import json
from config.config import URL_ENV_TEST, URL_ENV_BETA, URL_ENV_SOA, NOW_ENV, ENV_VARIABLE_PATH, test_request_parameters, \
    soa_request_parameters, beta_request_parameters
from core.TestFunction import TestFunction
from core.YamlLoad import read_center_params
from utils.Mysql import db
from utils.Tools import search
from utils.logger import log


def ReplaceNone(data):
    """替换为空数据"""
    data = str(data)
    data = data.replace("None", "''")
    data = data.replace("''''", "''")
    return eval(data)


def replace_keywords(data):
    data = str(data)
    data = data.replace('false', "'false'")
    data = data.replace('False', "'False'")
    return eval(data)


def data_processing(data):
    """请求前的数据处理"""
    log.info("替换请求中的一些关键字.")
    data = replace_keywords(data)
    log.info("开始提取yaml_data中的变量，并进行替换.")
    data = replace_dict(data)
    log.info("开始提取yaml_data中的环境变量,并进行替换.")
    data = load_env_variable(data)
    log.info("开始读取yaml_data中的方法调用，并进行替换.")
    data = run_function(data)
    log.info("开始替换为空的数据.")
    data = ReplaceNone(data)
    log.info("开始替换文件中的sql语句")
    data = replace_db(data)
    log.info("实际请求的数据如下:\n%s" % str(data))
    data = replace_data(data)
    return data


def replace_data(yaml_data):
    """修改request传递的参数名称"""
    # 如果请求方式是get，则请求的参数用params传递
    if 'data' in json.dumps(yaml_data["requests"]):
        if yaml_data["method"].lower() == "get":
            yaml_data["requests"]["params"] = yaml_data["requests"]["data"]
            yaml_data["requests"].pop("data")
            log.info("请求模式为GET,请求参数名更换为: params")
            # 如果说请求方式是post，且需要用json传参，则把请求参数修改为json
        elif yaml_data["method"] == "post":
            headers = yaml_data["requests"]["headers"].keys()
            if "Content-Type" in headers or "content-type" in headers:
                temp_type = yaml_data["requests"]["headers"].get("Content-Type")
                if not temp_type:
                    temp_type = yaml_data["requests"]["headers"].get(
                        "content-type")
                if "application/json" in temp_type:
                    temp_str = yaml_data["requests"]["data"]
                    yaml_data["requests"]["data"] = json.dumps(yaml_data["requests"]["data"])
                    if temp_str != 'null' and temp_str != "":
                        yaml_data["requests"]["json"] = eval(yaml_data["requests"]["data"])
                    else:
                        yaml_data["requests"]["json"] = {}
                    yaml_data["requests"].pop('data')
                    log.info("请求方式为POST,且传参类型为:'application/json',将请求参数名修改为:json")
    else:
        log.info("用例中的data参数名已被替换.")
        pass
    log.info("请求参数名称修改完成.")
    return yaml_data


def load_env_variable(data):
    """读取环境变量"""
    try:
        data = str(data)
        get_list = search(data, "$ev{", "}")
        if NOW_ENV == "TEST":
            env_variables = test_request_parameters
        elif NOW_ENV == "BETA":
            env_variables = beta_request_parameters
        elif NOW_ENV == "SOA":
            env_variables = soa_request_parameters
        else:
            env_variables = {}
            log.error("运行环境设置有误，请检查!")
        if get_list:
            get_list = set(get_list)
            for each in get_list:
                if each:
                    try:
                        if isinstance(env_variables[each], list):
                            data = data.replace("'$ev{%s}'" % each, str(env_variables[each]))
                        else:
                            data = data.replace("$ev{%s}" % each, str(env_variables[each]))
                    except KeyError:
                        log.error("环境变量文件中，没有找到%s 对应的值." % each)
                        raise
        return eval(data)
    except NameError as ex:
        msg = '麻烦时间日期打个单引号!'
        log.error(msg)
        raise NameError(msg)


def replace_dict(data, start_str="${", end_str="}"):
    """读取接口提取的变量"""
    data = str(data)
    extract_data = read_center_params()
    temp_list = search(data, start_str, end_str)
    if temp_list:
        for each in temp_list:
            if each:
                if each in extract_data.keys():
                    value = extract_data[each]
                else:
                    log.error("extract文件中未找到该值.")
                    value = None
                data = data.replace(start_str + each + end_str, str(value))
    return eval(data)


def replace_db(data, start_str="$db{", end_str="}"):
    """读取请求的sql"""
    data = str(data)
    extract_data = read_center_params()
    temp_list = search(data, start_str, end_str)
    if temp_list:
        for each in temp_list:
            if each:
                value = db.load_db(each)
            else:
                log.info('sql内容为空，执行不了')
                value = ''
            data = data.replace(start_str + each + end_str, str(value))
    return eval(data)


def get_url(env):
    """读取测试的环境"""
    log.info("识别测试环境！")
    if env.lower() == "test":
        domain_name = URL_ENV_TEST
    elif env.lower() == "beta":
        domain_name = URL_ENV_BETA
    elif env.lower() == "soa":
        domain_name = URL_ENV_SOA
    else:
        log.error("配置文件中的环境设置不正确！")
        raise KeyError("配置文件中的环境设置不正确！！")
    log.info("需要测试的环境为 :(%s)" % str(domain_name))
    return domain_name


def run_function(data):
    """运行yaml文件中的函数"""
    data = str(data)
    func_list = search(data, "$f{", "}")
    if func_list:
        log.info("数据中包含的函数为: %s" % str(func_list))
        for func in func_list:
            if "(" in func and ")" in func:
                func_name = func[0:func.find('(')]
                if func_name in TestFunction().methods():
                    func_str = "TestFunction()." + func
                    value = eval(func_str)
                    log.info("函数(%s)执行完成，执行结果为: %s" % (func, value))
                    data = data.replace('$f{' + func + '}', str(value))
                else:
                    log.error("没有这个函数，检查一下函数名是否错误：%s" % func_name)
            else:
                log.error("函数调用需要加上括号以及对应参数.该函数格式错误： %s" % func)
    else:
        log.info("数据中没有调用函数!")
    return eval(data)
